JS - werken met objecten
Home

JS - werken met objecten

JS - werken met objecten

JavaScript is gebaseerd op een eenvoudig objectgeoriënteerd ontwerp.

Doelstelling

Na deze les weet je dat:

  1. een object bestaat uit een verzameling eigenschappen;
  2. een eigenschap is een koppeling tussen een naam (of sleutel) en een waarde;
  3. de waarde van een eigenschap kan een primitief gegevenstype zijn, Number, Boolean, String, ...
  4. vermits functies 'first class citizen' zijn, namelijk functies zijn data, een eigenschap die gekoppeld is aan een functie een methode is;
  5. er naast objecten die vooraf zijn gedefinieerd zijn, ook zelfgemaakte objecten bestaan;
  6. hoe je met eigenschappen, functies en methoden je eigen objecten kunt maken;
  7. Overzicht van de doelstellingen:

Stappenplan

  1. Overzicht
  2. We vertrekken van de oefening uit OO programmeren in C# en we maken de Studentklasse in JS. Heb je nog geen kennis van C#, kan je de vergelijking met C# negeren:
    1. Deze klasse heeft 6 eigenschappen:
      1. Name (string)
      2. Age (byte)
      3. ClassGroup (maak hiervoor een enum ClassGroups)
      4. MarkCommunication (byte)
      5. MarkProgrammingPrinciples (byte)
      6. MarkWebTech (byte)
    2. Leeftijd en de punten stel je voor met full properties.
    3. Een student kan nooit ouder zijn dan 120.
    4. Je kan ook nooit een negatief cijfer of een cijfer boven 20 behalen.
    5. Voeg aan de klasse een read-only property OverallMark toe. Deze berekent het gemiddelde van de 3 punten als double.
    6. Voeg aan de klasse ook de methode ShowOverview() toe. Deze methode zal een volledig rapport van de student tonen (inclusief het gemiddelde m.b.v. de OverallMark-property).
    7. Test je programma door enkele studenten aan te maken en in te stellen.
  3. Een enum is een gegevenstype dat gebruikt wordt voor een opsomming van gelijkaardige elementen. Bijvoorbeeld de dagen van de week. De klassengroep in de Student klasse bevat een lijst van klassengroepen, namelijk EA1, EA2, EA3. JavaScript beschikt niet over enum zoals C#. Daar passen we een mouw aan en we gebruiken een eenvoudig object om een enum voor te stellen. En object is tenslotte een lijst van eigenschappen die een koppeling legt tussen een sleutel en een waarde. Hier in dat geval is de sleutel gelijk aan de waarde:
    // in JavaScript bestaan er geen enums.
    // we gaan een enum nabootsen door gebruik
    // te maken van een object
    // vermits we dat object nooit gaan wijzigen
    // declareren we het als een const
    
    const classGroups = {
       EA1: 'EA1',
       EA2: "EA2",
       EA3: "EA3"
    
    };
    

    We maken hier een literal object, een letterlijk object. We gebruiken geen OO syntaxis maar een soort van template: een door komma's gescheiden lijst van sleutel-waardeparen die tussen accolades staan. Object literals kapselen gegevens in, in een mooi afgebakend pakket.

  4. const
    Het object hierboven hebben we als const gedeclareerd. De lijst van klassengroepen stoppen we in een constante omdat de klassengroepen van te voren vast liggen en door het programma nooit zullen en mogen gewijzigd worden.

  5. We gaan onze eerste student als een object literal aanmaken:

     let student1 = {
        name: 'Bob Dylan',
        age: 54,
        classGroup: classGroups.EA2,
        markCommunication: 18,
        markProgrammingPrinciples: 20,
        markWebTechnology: 19,
        overallMark: function() {return (this.markCommunication +
              this.markProgrammingPrinciples +
              this.markWebTechnology) / 3;},
        showOverview: function () {
           return `Overzicht rapport:
              Naam: ${this.name}
              Klasgroep: ${this.classGroup}
              Leeftijd: ${this.age}
              Punten 
                 Communicatie: ${this.markCommunication}
                 PP: ${this.markProgrammingPrinciples}
                 WebTechnolgy: ${this.markWebTechnology}
                 Gemiddelde: ${this.overallMark()}`;
        }
     };
     console.log(student1.showOverview());

    Hier zien we een paar interessante dingen. We hebben een reeks eigenschappen die enkele kenmerken van een student beschrijft, o.a. leeftijd, punten voor verschillende vakken, de naam. Maar er staan twee bijzondere eigenschappen in, namelijk overallMark en showOverview. Aan die twee sleutels worden ook data gekoppeld maar 't is wel speciale data, het zijn namelijk functies. En dat is niet meer zo eigenaardig als we in ons achterhoofd houden dat functies in JavaScript First citizen's zijn, namelijk data net zoals Number en String. Die twee eigenschappen worden dan geen eigenshappen meer genoemd maar methoden.

  6. let
    Het object Student hebben we met let gedeclareerd. Student is geen const omdat de waarden ervan tijdens het verloop van het programma gewijzigd kunnen worden. Alle variabelen declareer je met let of const.

  7. Stringinterpolatie met de backtick `

    Je kan JavaScript code binnenin een string gebruiken als je de string tussen twee backticks plaatst. De JavaScript code plaats je tussen accolades en je zet er een $ teken voor. Let erop dat je de string ook over meer dan één lijn kan schrijven. Dat laat je toe de string formatteren:

    return `Overzicht rapport:
        Naam: ${this.name}
        Klasgroep: ${this.classGroup}
        Leeftijd: ${this.age}
        Punten 
            Communicatie: ${this.markCommunication}
            PP: ${this.markProgrammingPrinciples}
            WebTechnolgy: ${this.markWebTechnology}
            Gemiddelde: ${this.overallMark()}`
    

    De spaties en de nieuwe regels (new line) zullen op het scherm getoond worden. Je hoeft dus geen escape sign (\n) gebruiken om aan te geven dat je naar de volgende lijn wil gaan op het scherm.

    template strings with backtick
    template strings with backtick

    In JavaScript spreekt men van Template literals of Template strings.

  8. this
    Met het sleutelwoord this kan je binnen een methode verwijzen naar andere eigenschappen in het huidige object. Dit gebruiken bv in de anonieme functie die in overallMark zit: (this.markCommunication + this.markProgrammingPrinciples + this.markWebTechnology) / 3;

  9. Anonieme functies
    In het Student object hierboven hebben we een functies toegekend aan de eigenschappen overallMark en showOverview. Deze functies hebben geen naam en daarom spreekt men van anonieme functies of functies zonder naam. Waarom doen we dat. Wel eerlijk gezegd een beetje uit luiheid. Ik heb geen zin om eerste een functie met een naam te schrijven en dan die naam toe te kennen aan de eigenschap. Het gaat veel sneller om een anonieme functie ter plekke te schrijven en zonder omwegen in die eigenschap te proppen. Dus hier zie je wat een anonieme functie betekent en ook een voorbeeld waarom je zo'n ding in bepaalde omstandigheden nuttig kan zijn.

  10. Eventueel probleem met anonieme functies
    We maken nog een Student object literal:

    let student2 = {
    name: 'Sareh El Farisi',
    age: 24,
    classGroup: classGroups.EA3,
    markCommunication: 19,
    markProgrammingPrinciples: 20,
    markWebTechnology: 19,
    overallMark: function() {return
       (this.markCommunication +
       this.markProgrammingPrinciples +
       this.markWebTechnology) / 3; }, 
    showOverview: function () {
        return `Overzicht rapport:
           Naam: ${this.name}
           Klasgroep: ${this.classGroup}
           Leeftijd: ${this.age}`;}
    };

    Ik heb nu twee studenten met elk twee dezelfde anonieme functies. Als er nog een paar studenten bij komen ga ik mijn luiheid van daarstraks duur betalen. Ik moet voor elke student die anonieme functies intypen. En veronderstel dat er iets in één van die anonieme functies gewijzigd moet worden. Dan moet ik dat op evenzoveel plaatsen wijzigen als dat er studenten zijn.

  11. Functies met een naam of named functions
    Ik schrijf nu twee functies met een naam:

    function showOverview() {
    return `Overzicht rapport (met een named function):
    Naam: ${this.name}
    Klasgroep: ${this.classGroup}
    Leeftijd: ${this.age}
    Punten
        Communicatie: ${this.markCommunication}
        PP: ${this.markProgrammingPrinciples}
        WebTechnolgy: ${this.markWebTechnology}
        Gemiddelde: ${this.overallMark()}`;
    }
    
    function overallMark() {
    return (this.markCommunication +
        this.markProgrammingPrinciples +
        this.markWebTechnology) / 3;
    }

    En we overschrijven de methode eigenschappen in de twee Student objecten:

    // we kunnen een eigenschap met een nieuwe waarde overschrijven
    // hier overschrijven we de anonieme functie met een functie met een naam
    student1.overallMark = overallMark;
    student1.showOverview = showOverview;
    console.log(student1.showOverview())
    
    student2.overallMark = overallMark;
    student2.showOverview = showOverview;
    console.log(student2.showOverview())
    

    Als we één van de functies willen wijzigen moeten we dat maar op één plaats doen, namelijk in de desbetreffende named function. Neem aan dat we de naam van de student in hoofdletters willen tonen dan wijzigen we de functie met de naam showOvervieuw als volgt:

    function showOverview() {
        return `Overzicht rapport (met een named function):
        Naam: ${this.name.toUpperCase()}
        Klasgroep: ${this.classGroup}
        Leeftijd: ${this.age}
        Punten
            Communicatie: ${this.markCommunication}
            PP: ${this.markProgrammingPrinciples}
            WebTechnolgy: ${this.markWebTechnology}
            Gemiddelde: ${this.overallMark()}`;
    }

    Op één plaats de code wijzigen, en alle namen van de studenten worden in hoofdletter getoond!

  12. Alles is nog niet niet gezegd over werken met objecten. In een volgende les leren we:

    1. objecten maken met de new Object() constructor;

    2. werken met arrays van object;
    3. werken met de forEach, map, reduce en filder functies van array's
    4. Encapsulatie met het function object;

Code

Hier volgt de volledige code. Plaats het in een bestand met de naam werken-met-objecten1.js:

// in JavaScript bestaan er geen enums.
// we gaan een enum nabootsen door gebruik
// te maken van een object
// vermits we dat object nooit gaan wijzigen
// declareren we het als een const

const classGroups = {
    EA1: 'EA1',
    EA2: "EA2",
    EA3: "EA3"
 
 };

function showOverview() {
    return `Overzicht rapport (met een named function):
    Naam: ${this.name.toUpperCase()}
    Klasgroep: ${this.classGroup}
    Leeftijd: ${this.age}
    Punten
        Communicatie: ${this.markCommunication}
        PP: ${this.markProgrammingPrinciples}
        WebTechnolgy: ${this.markWebTechnology}
        Gemiddelde: ${this.overallMark()}`;
}

function overallMark() {
return (this.markCommunication +
    this.markProgrammingPrinciples +
    this.markWebTechnology) / 3;
}

 let student1 = {
    name: 'Bob Dylan',
    age: 54,
    classGroup: classGroups.EA2,
    markCommunication: 18,
    markProgrammingPrinciples: 16,
    markWebTechnology: 12,
    overallMark: function() {return (this.markCommunication +
          this.markProgrammingPrinciples +
          this.markWebTechnology) / 3;},
    showOverview: function () {
       return `Overzicht rapport:
          Naam: ${this.name}
          Klasgroep: ${this.classGroup}
          Leeftijd: ${this.age}
          Punten
             Communicatie: ${this.markCommunication}
             PP: ${this.markProgrammingPrinciples}
             WebTechnolgy: ${this.markWebTechnology}
             Gemiddelde: ${this.overallMark()}`;
    }
 };
 console.log(student1.showOverview());

 let student2 = {
    name: 'Sareh El Farisi',
    age: 54,
    classGroup: classGroups.EA2,
    markCommunication: 18,
    markProgrammingPrinciples: 20,
    markWebTechnology: 19,
    overallMark: function() {return (this.markCommunication +
          this.markProgrammingPrinciples +
          this.markWebTechnology) / 3;},
    showOverview: function () {
    return `Overzicht rapport:
        Naam: ${this.name}
        Klasgroep: ${this.classGroup}
        Leeftijd: ${this.age}
        Punten
            Communicatie: ${this.markCommunication}
            PP: ${this.markProgrammingPrinciples}
            WebTechnolgy: ${this.markWebTechnology}
            Gemiddelde: ${this.overallMark()}`;
    }
 };
 console.log(student2.showOverview());

// we kunnen een eigenschap met een nieuwe waarde overschrijven
// hier overschrijven we de anonieme functie met een functie met een naam
student1.overallMark = overallMark;
student1.showOverview = showOverview;
console.log(student1.showOverview())

student2.overallMark = overallMark;
student2.showOverview = showOverview;
console.log(student2.showOverview())

Bronnen

MDN web docs, Working with objects

JI
2020-03-25 09:45:55